<template>
  <div class="app-container-table">
      <a-spin :spinning="spinning">
          <div v-if="options.tip" class="app-container-table--tip">提示：{{ options.tip }}</div>
          <searchForm
              ref='searchFormRef'
              v-if="!options.hideSearch"
              :options="options"
              @change-search-handle="searchHandle"
              @search-change="searchChange"
              @search-reset="searchReset"
              @to-add="toAdd"
              @to-all-delete="toAllDel"
          ></searchForm>
          <slot name="slot_table_header"></slot>
          <a-table
              v-if="isShowTable"
              :columns="options.column.filter((itme: any) => !itme.hide)"
              :data-source="data"
              :expandIcon="(props: any) => expandIcon(props)"
              :expandedRowKeys="options.expandedRowKeys"
              :indentSize="options.indentSize"
              :pagination="options.pagination || false"
              :row-selection="
                  options.selection
                      ? {
                            selectedRowKeys: state.selectedRowKeys,
                            onChange: onSelectChange,
                            getCheckboxProps: options.getCheckboxProps || void 0
                        }
                      : null
              "
              :locale="options.emptyText || emptyText"
              :rowKey="options.rowKey"
              :size="options.size || 'middle'"
              :sticky="options.sticky || false"
              @change="changePage"
              @expand="onExpand"
          >
              <template></template>
              <template #bodyCell="scope">
                  <template v-if="scope.column.slot">
                      <slot :scope="scope" name="slot_cell"></slot>
                  </template>
                  <a-space v-if="scope.column.key === 'action'" size="middle">
                      <slot :scope="scope" name="slot_action_befor"></slot>
                      <a
                          v-if="options.editBtn(scope.record) && (options.permissions? options.permissions.edit : true)"
                          @click="toRowEdit(scope)"
                      >
                          编辑
                      </a>
                      <a
                          v-if="options.delBtn(scope.record) && (options.permissions? options.permissions.del : true)"
                          @click="toRowdel(scope)"
                      >
                          删除
                      </a>
                      <slot :scope="scope" name="slot_action_after"></slot>
                  </a-space>
              </template>
          </a-table>
          <slot name="slot_pagination"></slot>
      </a-spin>
      <a-modal
          v-model:open="modalVisible"
          :confirm-loading="confirmLoading"
          :title="`${options.TYPE_MODEL_REMARK ? options.TYPE_MODEL_REMARK[modalType] : TYPE_MODEL_REMARK[modalType]}${options.modalTitle}`"
          centered
          @cancel="doCancel"
          @ok="doOk"
      >
          <a-form
              v-if="modalVisible"
              :label-col="{ style: { width: `${options.labelWidth || 80}px` } }"
              class="crud-form"
          >
              <template v-for="item in modelColumn" :key="item.key">
                  <a-form-item :label="item.title" v-bind="useFormObj.validateInfos[item.key]">
                      <a-input
                          v-if="item.type === 'text' || !item.type"
                          v-model:value.trim="modelRef[item.key]"
                          :maxlength="item.maxlength || 40"
                          :disabled="
                              typeof item.disabled === 'function'
                                  ? item.disabled(modelRef)
                                  : item.disabled || false
                          "
                          :placeholder="item.placeholder || item.searchPlaceholder || '请输入'"
                      ></a-input>
                      <a-input-password
                          v-if="item.type === 'password'"
                          v-model:value.trim="modelRef[item.key]"
                          :maxlength="item.maxlength || 40"
                          :disabled="
                              typeof item.disabled === 'function'
                                  ? item.disabled(modelRef)
                                  : item.disabled || false
                          "
                          :placeholder="item.placeholder || item.searchPlaceholder || '请输入'"
                      ></a-input-password>
<!--                            v-model:searchValue="item.searchFilterValue"-->
                      <a-tree-select
                          v-if="item.type === 'treeSelect'"
                          v-model:treeExpandedKeys="item.FormExpandedRowKeys"
                          v-model:value="modelRef[item.key]"
                          :treeDefaultExpandAll="item.treeDefaultExpandAll || false"
                          :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
                          :dropdownMatchSelectWidth="false"
                          :fieldNames="item.fieldNames"
                          :disabled="
                              typeof item.disabled === 'function'
                                  ? item.disabled(modelRef)
                                  : item.disabled || false
                          "
                          :key="item.componentKey"
                          :filterTreeNode="item.filterTreeNode || false"
                          :labelInValue="item.labelInValue || false"
                          :load-data="item.onLoadData"
                          :placeholder="item.placeholder || item.searchPlaceholder || '请选择'"
                          :show-checked-strategy="item.showCheckedStrategy"
                          :showArrow="true"
                          :showSearch="item.showSearch || false"
                          :tree-checkable="item.treeCheckable || false"
                          :tree-data="item.dicData"
                          allow-clear
                          style="width: 100%"
                          @search="item.searchFetch"
                          @select="(value: any, node: any, extra: any) => selectHandle(value, node, extra, item)"
                      >

                          <template #title="scope">
                              <span v-if="scope.contextId" class='loading-more-style' @click.stop='item.loadingMore(scope)'>{{ scope[item.fieldNames.label] }} <i class='icon-zhankai'></i></span>
                              <template v-else>{{ scope[item.fieldNames.label] }}</template>
                          </template>

                      </a-tree-select>
                      <!-- 树结构展示 -->
                      <a-tree
                          v-if="item.type == 'tree'"
                          v-model:value="modelRef[item.key]"
                          v-model:expandedKeys="item.FormExpandedRowKeys"
                          v-model:selectedKeys="item.searchFilterValue"
                          v-model:checkedKeys="item.checkedKeys"
                          :checkStrictly="item.checkStrictly || false"
                          :fieldNames="item.fieldNames"
                          checkable
                          :height="233"
                          :defaultExpandAll="item.defaultExpandAll"
                          :tree-data="item.dicData"
                          @check="(v:any, info: any)=>handleCheck(v,info, item)"
                      >
                          <template #title="scope">
                              <span>
                                  {{ scope?.name }}
                              </span>
                          </template>
                      </a-tree>
                      <a-select
                          v-if="item.type === 'select'"
                          v-model:value="modelRef[item.key]"
                          :allowClear="true"
                          :fieldNames="item.fieldNames"
                          :max-tag-count="item.maxTagCount"
                          :disabled="
                              typeof item.disabled === 'function'
                                  ? item.disabled(modelRef)
                                  : item.disabled || false
                          "
                          :mode="item.mode"
                          :options="item.dicData"
                          :placeholder="item.placeholder || item.searchPlaceholder || '请选择'"
                          :showArrow="true"
                          style="width: 100%"
                      ></a-select>
                      <a-radio-group
                          v-if="item.type === 'radio'"
                          v-model:value="modelRef[item.key]"
                          :disabled="
                              typeof item.disabled === 'function'
                                  ? item.disabled(modelRef)
                                  : item.disabled || false
                          "
                          :options="item.dicData"
                          @change="
                              e => {
                                  item.select &&
                                      item.select(e.target, modelRef, setCoDicDisabled);
                              }
                          "
                      />
                  </a-form-item>
              </template>
          </a-form>
      </a-modal>
  </div>
</template>
<script lang="ts" setup>
import {
  ref,
  h,
  toRefs,
  toRaw,
  reactive,
  defineEmits,
  defineProps,
  defineExpose,
  nextTick,
  watchEffect
} from 'vue';
import {
  CaretRightOutlined,
  CaretDownOutlined,
  ExclamationCircleFilled
} from '@ant-design/icons-vue';
import searchForm from '@/package/tableCrud/search-form.vue';
import { Empty, Form, Modal, TableProps } from 'ant-design-vue';
import pic_default from '@/assets/pic_default.svg';
import { isShowFormItem } from '@/package/tableCrud/utils';
import {TYPE_MODEL, TYPE_MODEL_REMARK} from '@/types/component.ts'
const emits = defineEmits([
  'search-change',
  'search-reset',
  'onExpand',
  'changePage',
  'toAdd',
  'doAdd',
  'doEdit',
  'doRowdel',
  'doSearch',
  'onSelectChange',
  'clearSelect',
  'to-edit'
]);
const props = defineProps({
  options: {
      type: Object,
      default: () => {
          return {
              column: []
          };
      }
  },
  data: {
      type: Object,
      default: () => {
          return [];
      }
  },
  isShowTable: {
      type: Boolean,
      default: true
  },
});
const searchFormRef = ref<any>(null);
type Key = string | number;
const state = reactive<{
  selectedRowKeys: Key[];
  loading: boolean;
}>({
  selectedRowKeys: [], // Check here to configure the default column
  loading: false
});
const emptyText = ref({
  emptyText: h(Empty, {
      description: '暂无数据',
      image: pic_default,
      imageStyle: { height: '138px' },
      style: { color: 'rgba(0, 0, 0, 0.65)', fontSize: 14, lineHeight: '22px' }
  })
});

function onSelectChange(selectedRowKeys: Key[]) {
  state.selectedRowKeys = selectedRowKeys;
  emits('onSelectChange', selectedRowKeys);
}

function clearSelect(selectedRowKeys: Key[]) {
  state.selectedRowKeys = [];
  emits('clearSelect');
}
const handleCheck = (v: any, info: any, item: any) => {
  modelRef.value[item.key] = v;
};

/**
* @description 模糊查询
* @param type
* @param data
*/
const searchHandle = (type: any, data: any) => {
  console.log('searchHandle', type, data);
  emits('change-search-handle', type, data);
};


function EchoSelection(selectedRowKeys) {
  state.selectedRowKeys = selectedRowKeys;
}

const confirmLoading = ref<boolean>(false);
const spinning = ref<boolean>(false);


const modalType = ref<TYPE_MODEL>(TYPE_MODEL.ADD);
const modalVisible = ref<boolean>(false);
const { options, data, isShowTable } = toRefs(props);
const modelRef: any = ref<any>({});
const modelRules = ref<any>(null);
const useFormObj = ref<any>({});
const modelColumn = ref<any[]>([]);

function resetForm() {
  const column = toRaw(options.value).column.filter(item => {
      if (modalType.value === TYPE_MODEL.EDIT) {
          if (typeof item.displayEdit === 'function') {
              return item.displayEdit(modelRef.value);
          }
          return item.displayEdit !== false;
      } else if (modalType.value === TYPE_MODEL.ADD) {
          if (typeof item.displayAdd === 'function') {
              return item.displayAdd(modelRef.value);
          }
          return item.displayAdd !== false;
      }
      return false;
  });

  modelRef.value = column.reduce((acc, cur) => {
      if (cur.treeCheckable) {
          acc[cur.key] = [];
      } else {
          acc[cur.key] = null;
      }
      return acc;
  }, {});
}

function setModelColumn() {
  modelColumn.value = toRaw(options.value).column.filter(item => isShowFormItem(item, modalType.value, modelRef.value));
}

function setRules() {
  const column = toRaw(options.value).column.filter(item => {
      if (modalType.value === TYPE_MODEL.EDIT) {
          if (typeof item.displayEdit === 'function') {
              return item.displayEdit(modelRef.value) && item.rules;
          }
          return item.displayEdit !== false && item.rules;
      } else if (modalType.value === TYPE_MODEL.ADD) {
          if (typeof item.displayAdd === 'function') {
              return item.displayAdd(modelRef.value) && item.rules;
          }
          return item.displayAdd !== false && item.rules;
      }
      return false;
  });
  console.log('column', column);
  const modelRulesArr = column.map(item => {
      return {
          key: item.key,
          rules: item.rules
      };
  });
  modelRules.value = modelRulesArr.reduce((acc, cur) => {
      acc[cur.key] = cur.rules;
      return acc;
  }, {});
}

const $index = ref<any>(null);

const useForm = Form.useForm;

function selectHandle(value, node, extra, item) {
  if (!item.select) return false;
  item.select(value, node, item, newValue => {
      modelRef.value[item.key] = newValue;
  });
}

function expandIcon(pro: any) {
  const styleEvent: any = {
      style: { color: '#BDBDBD', marginRight: '10px' },
      onclick: (e: any) => {
          pro.onExpand(pro.record, e);
      }
  };
  if (!pro.record.children) return;
  if (pro.expanded) {
      return h(CaretDownOutlined, styleEvent);
  }
  return h(CaretRightOutlined, styleEvent);
}

function onExpand(expanded: any, record: any) {
  console.log(expanded, record);
  emits('onExpand', expanded, record);
}

function toAdd() {
  modalType.value = TYPE_MODEL.ADD;
  emits('toAdd');
  setModelColumn();
  resetForm();
  setRules();
  useFormObj.value = useForm(modelRef, reactive(modelRules.value));
  nextTick(() => {
      modalVisible.value = true;
  });
}

function toAllDel() {
  Modal.confirm({
      title: '删除',
      centered: true,
      icon: h('i', null, null),
      content: h(
          'div',
          {
              style: {
                  color: 'rgba(0,0,0,0.85)',
                  fontSize: '16px',
                  lineHeight: '21px',
                  margin: '24px 0 56px'
              }
          },
          [
              h(ExclamationCircleFilled, {
                  style: { color: '#FAAD14', fontSize: '21px', marginRight: '16px' }
              }),
              options.value.delAllConfirmTip || '确认是否批量删除？'
          ]
      ),
      onOk() {
          return new Promise((resolve: any) => {
              emits('doAllDel', state.selectedRowKeys, () => {
                  state.selectedRowKeys = [];
                  resolve();
              });
          }).catch(() => console.log('Oops errors!'));
      },
      // eslint-disable-next-line @typescript-eslint/no-empty-function
      onCancel() {}
  });
}

const changePage: TableProps['onChange'] = params => {
  console.log('changePage', params);
  spinning.value = true;
  emits('changePage', params, loadingEnd);
};

const setCoDicDisabled = (key, value, disabled) => {
  const column = modelColumn.value.find(co => co.key === key);
  if (column && column.dicData?.length) {
      const dicData = column.dicData.find(dic => dic.value == value);
      if (dicData) {
          dicData.disabled = disabled;
      }
  }
};

function doOk() {
  confirmLoading.value = true;
  useFormObj.value
      .validate()
      .then(() => {
          if (modalType.value === TYPE_MODEL.ADD) {
              emits('doAdd', JSON.parse(JSON.stringify(modelRef.value)), loadingEnd, doCancel);
          } else if (modalType.value === TYPE_MODEL.EDIT) {
              console.log('modelRef.value', modelRef.value, $index.value);
              emits(
                  'doEdit',
                  JSON.parse(JSON.stringify(modelRef.value)),
                  $index.value,
                  loadingEnd,
                  doCancel
              );
          }
      })
      .catch(err => {
          console.log('validate error', err);
          confirmLoading.value = false;
      });
}

function loadingEnd() {
  confirmLoading.value = false;
  spinning.value = false;
}

function doCancel() {
  for (let key in modelRef.value) {
      modelRef.value[key] = null;
  }
  modalVisible.value = false;
  confirmLoading.value = false;
  useFormObj.value.resetFields();
  loadingEnd();
}

async function toRowEdit(scope: any) {
  emits('to-edit', scope);
  modalType.value = TYPE_MODEL.EDIT;
  $index.value = scope.index;
  resetForm();
  for (let key in scope.record) {
      console.log('toRowEdit-name', key);
      modelRef.value[key] = scope.record[key];
  }
  console.log('toRowEdit', scope, modelRef.value);
  if (options.value.toRowEdit) {
      const rowData = await options.value.toRowEdit(scope.record);
      console.log('rowData1111:', rowData);
      modelRef.value = { ...modelRef.value, ...rowData };
      console.log('rowData', modelRef.value);
  }
  setModelColumn();
  setRules();
  useFormObj.value = useForm(modelRef, reactive(modelRules.value));
  modalVisible.value = true;
}

function toRowdel(scope: any) {
  console.log(scope);
  Modal.confirm({
      title: '删除',
      centered: true,
      icon: h('i', null, null),
      content: h(
          'div',
          {
              style: {
                  color: 'rgba(0,0,0,0.85)',
                  fontSize: '16px',
                  lineHeight: '21px',
                  margin: '24px 0 56px'
              }
          },
          [
              h(ExclamationCircleFilled, {
                  style: { color: '#FAAD14', fontSize: '21px', marginRight: '16px' }
              }),
              options.value.delConfirmTip || '确认是否删除？'
          ]
      ),
      onOk() {
          return new Promise((resolve: any) => {
              emits('doRowdel', scope, () => {
                  console.log('11111:', state.selectedRowKeys);
                  const index = state.selectedRowKeys.indexOf(scope.record[options.value.rowKey]);
                  state.selectedRowKeys.splice(index, 1);
                  resolve();
              });
          }).catch(e => console.log(e));
      },
      // eslint-disable-next-line @typescript-eslint/no-empty-function
      onCancel() {}
  });
}

const searchChange = (params: any) => {
  console.log(params);
  spinning.value = true;
  emits('doSearch', params, loadingEnd);
};
const searchReset = () => {
  console.log('清空搜索条件');
  emits('search-reset');
};

const setSearchDefault = () => {
  searchFormRef.value.setSearchDefault()
}

const refresh = () => {
  if (options.value.hideSearch) {
      return searchChange({});
  }
  searchFormRef.value.searchChange();
}

watchEffect(() => {
  console.log('watch---modelRef.value', modelRef.value);
});

defineExpose({
  toRowdel,
  toAllDel,
  clearSelect,
  EchoSelection,
  setModelColumn,
  setRules,
  setSearchDefault,
  refresh
});
</script>

<style lang="scss" scope>
.crud-form {
  margin: 40px;
}

.app-container-table {
  &--tip {
      color: #fb9d39;
      font-size: 14px;
      line-height: 20px;
      margin-bottom: 16px;
  }
}
.loading-more-style {
  width: 100%;
  text-align: center;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 12px;
}

.loading-more-style--table {
  text-align: center;
  align-items: center;
  font-size: 12px;
}

</style>
